package apibasej.db.transaction;

import java.util.ArrayList;
import java.util.LinkedHashMap;

import apibasej.db.to.ResultSelect;
import apibasej.db.to.StatementQuery;
import apibasej.db.to.StatementValues;

public class UtilExecStatement {

	private UtilExecStatement(){}
	
	public static ResultSelect execStatementQuery(GenericTransaction tr, StatementQuery sq) throws UtilDBException{
		try{
			ResultSelect rs = new ResultSelect();
			CursorSelect cs = tr.executeQuery(sq);
			int ctCols = cs.getCtCols();
			while( cs.next() ){
				LinkedHashMap<Integer,Object> lin = new LinkedHashMap<Integer,Object>();
				int index = 0;
				ArrayList<Class<?>> typesCols = sq.getTypesColsSelect();
				for(int i=0; i<ctCols; i++){
					Class<?> type = typesCols==null?Object.class:typesCols.get(i);
					Object v = cs.getValResultSet(type, false, i);
					lin.put(index,v);
					index++;
				}
				rs.getRows().add(lin);
			}
			cs.verifyCloseConnectionAfterExecute();// tem que verificar
			
			// seta o count
			if(sq.isReturnTotalCountWithoutPagination()){
				if(rs.getRows().size()<sq.getMaxResults() && sq.getFirstResult()==0){// se for primeira pagina tem menos que a qtd máxima não precisa do count
					rs.setTotalCountWithoutPagination(rs.getRows().size());
				}else{
					Integer total = cs.getTotalCountWithoutPagination();
					rs.setTotalCountWithoutPagination(total);
				}
			}
			//rs.setNameCols(cs.getNameCols());
			rs.setCtCols(ctCols);
			return rs;
			
		}catch (UtilDBException e) {	
			tr.verifyConnectionAfterError();// deve ser chamado antes do close()
			tr.close();// somente por segurança
			throw e;
		}catch (Throwable e) {
			tr.verifyConnectionAfterError();// deve ser chamado antes do close()
			tr.close();// somente por segurança
			throw new UtilDBException("Error on read response of select", e);
		}
	}
	
	public static int execStatementUpdate(GenericTransaction tr, StatementValues sv) throws UtilDBException{
		try {
			int linsAfetadas = tr.executeUpdate(sv);
			tr.verifyCloseAfterExecute();
			return linsAfetadas;
		} catch (Throwable e) {
			tr.verifyConnectionAfterError();// deve ser chamado antes do close()
			
			tr.close();
			
			//não adianta ignorar o close(), pois o postgre já invalida a transação depois de retornar um erro
			//if(!tr.isIgnoreCloseAfterError()){tr.close();}
			
			throw new UtilDBException("Error on execute SQL.",e); // não retornar SQL Info ... Error on execute SQL. SQL Info:
		}
	}
	
}
